# -*- coding: utf-8 -*-
from openerp.osv import fields
from openerp.osv import osv
from openerp import SUPERUSER_ID
"""
#1139 需要卡券订单减少数量向导，添加卡号、密码列表，确认后将这些卡券检验密码正确后禁用（需判断原状态，如果未启用、已经禁用、已经提货则报错） 
减少总的计划提货数和未提货数为输入的卡券数量
"""
    
class card_return_record(osv.osv):
    _name = 'card.return.record'

    def _set_default_product_id(self, cr, uid, context=None):
        order_row = self.pool.get('sale.order').browse(cr, uid, context.get('active_id'), context=context)
        for line in order_row.order_line:
            if line.product_id.default_code == order_row.name:
                return line.product_id.id
        return False

    _columns = {
         'order_id': fields.many2one('sale.order', string='对应的销售订单'),
         'product_id': fields.many2one('product.product'),
         #'card_lines': fields.one2many('order.card.return', 'return_record_id', string='退回的卡券')
         'active_number': fields.text(u'输入券号'),
         'check_active': fields.text(u'反馈信息'),
         'new_order_id': fields.many2one('sale.order', u'新创建的销售订单'),
    }
    _defaults = {
        'product_id': _set_default_product_id,
        'order_id': lambda self, cr, uid, context=None: context.get('active_id'),
    }

    def one_code_list_handle(self, cr, uid, code_list, record, old_val='未兑换', new_val='禁用', context=None):
        track_obj = self.pool.get('product.card.track')
        for line in self.pool.get('product.card.line').browse(cr, uid, code_list, context=context):
            if line.so_id.id != record.order_id.id:
                raise osv.except_osv(
                            u'警告', u'%s券号不属于销售订单%s！' % (line.code, line.so_id.name))
            track_obj.create(cr, SUPERUSER_ID, {'card_line_id': line.id,
                                                'code': line.code,
                                                'changed_field': u'%s销售订单中进行%s!' %(record.order_id.name,
                                                 new_val),
                                                'old_value': old_val,
                                                'new_value': new_val,
                                                'operation_type': 'disable',
                                                })
    
    def create_service_sale_line(self, cr, uid, change_product_row, order_id, context=None):
        line_obj = self.pool.get('sale.order.line')
        return line_obj.create(cr, uid, {
                'product_id': change_product_row.get('product_id'),
                'product_uom_qty': - change_product_row.get('product_uom_qty'),
                'price_unit': change_product_row.get('price_unit'),
                'name': change_product_row.get('name'),
                'delivered_qty': 0,
                'order_id': order_id,
                'sale_note': change_product_row.get('note'),
                'product_uos_qty': change_product_row.get('product_uom_qty'),
                'state': 'draft',
            }, context=context)

    def parse_text(self, cr, text):
        '''将文本解析为独立的code'''
        text = text.replace(
            ' ', '')  # 之后的几个替换主要是为了，防止用户不清楚解析规则胡乱输入分割的字符。把几个常见的不规范的字符替换成我们规定的能解析的字符。
        text = text.replace('-', '~')
        text = text.replace('－', '~')
        text = text.replace('～', '~')
        mis = 0  # 记录左侧text输入的卡券号所在
        res = []  # 存放解析出来的tuple列表，tuple第一个元素为行号，第二个元素为卡券号
        temp_list = text.split('\n')
        for temp in temp_list:
            row_code = 0  # 用来记录卡券区间一共包含多少张卡券
            mis += 1
            from_to = temp.split('~')
            current = from_to[0]
            res.append((mis, current))
            if len(from_to) == 2:
                while current != from_to[1]:
                    current = self.pool['product.card.issue'].get_next_n_number(current, 1)
                    res.append((mis, current))
                    row_code += 1
                    # 性能 报错
                    if len(current) != len(from_to[1]):
                        raise osv.except_osv(
                            u'警告', u'您输入的第%s行起始和结束卡券位数不一致，请重新输入！' % mis)
                    if current > from_to[1]:
                        raise osv.except_osv(
                            u'警告', u'您输入的第%s行起始卡券号大于结束卡券号，请重新输入！' % mis)
                    if row_code > 999:
                        raise osv.except_osv(
                            u'警告', u'您输第%s行卡券区间超过1000，请修改后再激活！' % mis)
        return res

    def check_active_number(self, cr, uid, ids, active_number,context=None):
        '''on_change校验左边输入的卡券号是否正确，若不正确在右边文本框会提示修改
                  若输入全部正确，这显示需要激活卡券的详情'''
        if active_number:
            card_line_obj = self.pool.get('product.card.line')
            user_obj = self.pool.get('res.users').browse(
                cr, uid, uid, context=context)
            res = ''  # 存放报错提示的字符串
            line_ids = []  # 根据一个卡券号取得的id列表
            line_idss = []  # 全部检查通过的卡券id，组成数列
            codes = []  # 从输入的text中，转成tuple后拿到的卡券号列表
            rows_tup = []  # 每个卡券号对应的行号
            codes.extend(self.parse_text(cr, active_number))
            for i in range(len(codes)):
                code_tup = codes[i][1]  # 券号
                rows_tup = codes[i][0]  # 行号
                line_ids = card_line_obj.search(
                    cr, uid, [('code', '=', code_tup)], context=context)
                if not line_ids:
                    res = '第' + str(rows_tup) + '行' + ',' + \
                        '卡券' + code_tup + '不存在'
                    return {'value': {'check_active': res}}
                for line_id in card_line_obj.browse(cr, uid, line_ids, context=context):
                    if not line_id.is_active:
                        res = '第' + str(rows_tup) + '行' + ',' + \
                            '卡券' + line_id.code + '未激活'
                        return {'value': {'check_active': res}}
                    if not line_id.is_enabled:
                        res = '第' + str(rows_tup) + '行' + ',' + \
                            '卡券' + line_id.code + '还未启用，请先启用！'
                        return {'value': {'check_active': res}}
                    if line_id.is_exchanged:
                        res = '第' + str(rows_tup) + '行' + ',' + \
                            '卡券' + line_id.code + '已经兑换!'
                        return {'value': {'check_active': res}}
                    # 每次循环取当前卡券号对应的归属方id加入列表
                line_idss.extend(line_ids)
            # 对归属方id列表去重，然后计算长度，如果长度大于1说明归属方不同，不能激活
            if len(line_idss) != len(list(set(line_idss))):
                return {'value': {'check_active': u'输入的券号有重复，请核对后在进行操作！'}}
            return {'value': {'check_active': self.get_message(cr, uid, line_idss, context=context)}}
            
    def get_message(self, cr, uid, line_ids, context=None):
        ret = ''
        product_list = []
        product_dict = {}
        all_qty = 0
        for card_line in self.pool['product.card.line'].browse(cr, uid, line_ids, context=context):
            if card_line.product_id.id not in product_list:
                product_list.append(card_line.product_id.id)
                product_dict.update(
                    {card_line.product_id.id: {'qty': 0, 'codes': []}})
            product_dict[card_line.product_id.id]['qty'] += 1
            product_dict[card_line.product_id.id][
                'codes'].append(card_line.code)
        
        for product_id in product_list:
            product = product_dict.get(product_id)
            product_row = self.pool.get('product.product').browse(
                    cr, uid, product_id, context)
            ret += '\n[%s]%s  %d张  \n' % (  product_row.default_code, product_row.name, product['qty'])
            ret += '\n'.join(self.build_code(product['codes']))
            all_qty += product['qty']
        ret += '\n'
        ret += u'待禁用' + str(all_qty) + u'张卡券' + '\n'
        return ret
    
    def build_code(self, codes):
        '''传入一个某一个产品的卡券编号列表，eg:['a001','a002','a0003','a005','a006']
                            返回的 也是一个列表,eg:['a001~a002','a0003','a005~a006'
                            把连续的卡券编号 分组]'''
        ret = []
        new_codes = sorted(codes)  # 升序排列codes
        new_codes.append('ssss')  # 在列表的最后面插入一个无效的元素，防止下面取值时取不到最后一个元素
        before = ''  # 前一个卡券号
        min = new_codes[0]  # 连续编号中最小的一个卡券号
        qty = 0
        for code in new_codes:
            if before != '' and self.pool['product.card.issue'].get_next_n_number(before, 1) != code:
                # 当前的跟前一个卡券号不连续的情况
                if min == before:
                    ret.append(u'%s (1张)' % before)
                else:
                    ret.append(u'%s ~ %s (%d张)' % (min, before, qty))
                min = code
                qty = 0
            before = code
            qty = qty + 1
        return ret

    def return_card_order(self, cr, uid, ids, context=None):
        card_line_obj = self.pool.get('product.card.line')
        order_obj = self.pool.get('sale.order')
        for record in self.browse(cr, uid, ids, context=context):
            line_ids = []
            text_list = record.check_active.split('\n')
            if len(text_list[0]) != 0:
                raise osv.except_osv(u'警告', u'您输入的券号有误，请修改正确后再激活！')
            codes = []
            codes.extend([x[1] for x in self.parse_text(cr, record.active_number)])
            line_ids.extend(card_line_obj.search(cr, uid, [('code', 'in', codes)], context=context))
            self.one_code_list_handle(cr, uid, line_ids, record, context=context)
            card_line_obj.write(cr, SUPERUSER_ID, line_ids, {'is_active': False}, context=context)
            record.order_id.write({'card_qty': record.order_id.card_qty - len(line_ids)})
            line_dict = []
            for sale_line in record.order_id.order_line:
                if sale_line.product_id.type == 'service':
                    line_dict.append({'product_id': sale_line.product_id.id,
                                    'product_uom_qty': len(list(set(line_ids))),
                                    'price_unit': sale_line.price_unit,
                                    'name': sale_line.name,
                                    'note': sale_line.sale_note,
                                    })
            sale_data = order_obj.copy_data(cr, uid, record.order_id.id, {
                'is_return': True,
                'is_card': False,
                'origin_so_id': record.order_id.id,
                'order_line': 'NULL',
                'note': record.check_active,
            })
            order_id = order_obj.create(cr, uid, sale_data, context=context)
            [self.create_service_sale_line(cr, uid, line, order_id, context) for line in line_dict]
            record.write({'new_order_id': order_id})
            return self.pool.get('product.package').return_action(cr, uid, order_id, 'dftg_ext', 'sale_order_purchase_confirm_action',
            'dftg_sale_order_form_sates', return_type='form', context=context)
    
    def back_return_card_order(self, cr, uid, ids, context=None):
        card_line_obj = self.pool.get('product.card.line')
        order_obj = self.pool.get('sale.order')
        for record in self.browse(cr, uid, ids, context=context):
            line_ids = []
            text_list = record.check_active.split('\n')
            if len(text_list[0]) != 0:
                raise osv.except_osv(u'警告', u'请联系管理员！')
            codes = []
            codes.extend([x[1] for x in self.parse_text(cr, record.active_number)])
            line_ids.extend(card_line_obj.search(cr, uid, [('code', 'in', codes), ('is_active', '=', False)], context=context))
            if len(set(line_ids)) != len(set(codes)):
                raise osv.except_osv(u'警告', u'本次激活数量和需要激活的数量不一致！')
            self.one_code_list_handle(cr, uid, line_ids, record, old_val='禁用', new_val='激活',context=context)
            card_line_obj.write(cr, SUPERUSER_ID, line_ids, {'is_active': True}, context=context)
            record.order_id.write({'card_qty': record.order_id.card_qty + len(line_ids)})
            line_dict = []
        return True
        

class card_password_line(osv.osv):
    _name = 'card.password.line'
    _columns = {
        'code': fields.many2one('product.card.line', string='Code line'),
        'copy_code': fields.char(string='卡券号码', required=True),
        'password': fields.char(string='密码', required=True),
        'return_record_id': fields.many2one('card.return.record', string='主记录')
    }


    def on_change_code_password(self, cr, uid, ids, copy_code, password, context=None):
        ''' 将输入的卡券号码转为卡券记录的id，并验证是否可以提货,然后验证用户名和密码是否匹配 '''
        # 若券号未输入，直接报错
        if not copy_code:
            if not password:
                return {}
            return {'warning': {'title': u'错误', 'message': u'请先输入卡券显示号码'}}

        card_line_id = self.pool['product.card.line'].search(
            cr, SUPERUSER_ID, [('code', '=', copy_code)], context=context)
        if card_line_id:
            card_line_id = card_line_id[0]  # 取输入券号的第一个id，转成int型
        else:
            return {'warning': {'title': u'错误', 'message': u'卡券号码不存在！'},
                    'value': {'password': '', 'copy_code': "", }}
        card_line = self.pool['product.card.line'].browse(
            cr, SUPERUSER_ID, card_line_id, context=context)
        # 先验证券号，如果验证失败报错，并清空券号和密码
        warning_msg = ''
        if not card_line_id:
            return {'warning': {'title': u'错误', 'message': copy_code + u'卡券号不存在'},
                    'value': {'copy_code': "", 'password': ""}}
        if not card_line.is_enabled:
            return {'warning': {'title': u'错误', 'message': copy_code + u'卡券未入库'},
                    'value': {'copy_code': "", 'password': ""}}
        if not card_line.is_active:
            return {'warning': {'title': u'错误', 'message': copy_code + u'卡券未出库 \n '},
                    'value': {'copy_code': "", 'password': ""}}
        if card_line.is_exchanged:
            return {'warning': {'title': u'错误', 'message': copy_code + u'卡券已被兑换'},
                    'value': {'copy_code': "", 'password': ""}}
        if password:
            # 只有管理员有密码表的读取权限
            if not self.pool['product.card.password'].search(cr, SUPERUSER_ID,
                                                             [('line_id', '=', card_line_id),
                                                              ('password', '=', password)],
                                                             context=context):
                return {'warning': {'title': u'错误', 'message': u"卡券号和密码不匹配"},
                        'value': {'password': ""}}
            # 只有券号和密码都输入了且匹配，才填充卡券id字段
            return {'value': {'code': card_line_id}}